package cosc455.project1;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Stack;

/**
 * SemanticAnalyzer main function is to convert a String ArrayList of tokens and
 * translate into a new HTML file. It passes the String ArrayList from the
 * parser into a reverse Stack. It empties the stack into a super string of
 * tokens and special formatting chars. It then writes the super string into an
 * HTML file.
 * 
 * @author BinhDang
 *
 */
public class SemanticAnalyzer {

	// String Stack of tokens
	public static Stack<String> stack = new Stack<String>();

	// Tab indentation counter
	private static int tabNum = 0;

	// String holder to compare
	private static String holder;

	// Super string that will be output to HTML file
	private static String superString = "";

	// Temporary String holder
	private static String tempText;

	private static BufferedWriter output;

	/**
	 * Initiates the SemanticAnalyzer Creates the stack and HTML file
	 * 
	 * @throws IOException
	 */
	public static void build() throws IOException {
		createStack();

		// Create html file
		File outFile = new File(Compiler.filePrefix + ".html");
		BufferedWriter output = new BufferedWriter(new FileWriter(outFile));

		// Iterate through stack until empty
		while (!stack.empty()) {
			holder = stack.pop();

			translate();
		}

		output.write(superString);
		// Traces html in console :off
		//System.out.print(superString);
		output.close();
	}

	/**
	 * Reverse Iterate through the String ArrayList of tokens and text and
	 * pushes onto a stack structure.
	 */
	public static void createStack() {
		for (int i = SyntaxAnalyzer.syntax.size() - 1; i >= 0; i--) {
			stack.push(SyntaxAnalyzer.syntax.get(i));
		}
	}

	/**
	 * Compares the elements of a stack through a switch block. Passes the token
	 * to a superString with the correct formatting.
	 */
	public static void translate() {
		switch (holder) {
		case "#StartDocument":
			holder = "<html>" + System.getProperty("line.separator");
			tabNum++;
			superString = superString + holder;
			break;
		case "#EndDocument":
			holder = System.getProperty("line.separator") + "</html>";
			superString = superString + holder;
			tabNum--;
			break;
		case "#StartHeading":
			holder = "<head>" + System.getProperty("line.separator");
			tabulate();
			tabNum++;
			superString = superString + holder;
			break;
		case "#EndHeading":
			holder = "</head>" + System.getProperty("line.separator");
			tabNum--;
			tabulate();
			superString = superString + holder;
			break;
		case "#StartTitle":
			holder = "<title>";
			tabulate();
			superString = superString + holder;
			tabNum++;
			break;
		case "#EndTitle":
			holder = "</title>" + System.getProperty("line.separator");
			superString = superString + holder;
			tabNum--;
			break;
		case "#StartComment":
			holder = "<!--";
			tabulate();
			superString = superString + holder;
			break;
		case "#EndComment":
			holder = "-->" + System.getProperty("line.separator");
			superString = superString + holder;
			break;
		case "#StartParagraph":
			holder = "<p>";
			superString = superString + System.getProperty("line.separator");
			tabulate();
			superString = superString + holder;
			tabNum++;
			break;
		case "#EndParagraph":
			tabNum--;
			holder = "</p>";
			superString = superString + System.getProperty("line.separator");
			tabulate();
			superString = superString + holder;
			break;
		case "#StartBold":
			holder = "<b>";
			superString = superString + holder;
			break;
		case "#EndBold":
			holder = "</b>";
			superString = superString + holder;
			break;
		case "#StartItalics":
			holder = "<i>";
			superString = superString + holder;
			break;
		case "#EndItalics":
			holder = "</i>";
			superString = superString + holder;
			break;
		case "#StartList":
			holder = "<ul>";
			superString = superString + System.getProperty("line.separator");
			tabulate();
			superString = superString + holder;
			tabNum++;
			break;
		case "#EndList":
			tabNum--;
			holder = "</ul>";
			superString = superString + System.getProperty("line.separator");
			tabulate();
			superString = superString + holder;
			break;
		case "#StartItem":
			tabNum++;
			holder = "<li>";
			superString = superString + System.getProperty("line.separator");
			tabulate();
			superString = superString + holder;
			break;
		case "#EndItem":
			tabNum--;
			holder = "</li>";
			superString = superString + holder;
			break;
		case "#StartAudio":
			holder = "<audio controls>" + System.getProperty("line.separator");
			superString = superString + holder;
			tabNum++;
			tabulate();
			superString = superString + "<source src=\"";
			break;
		case "#EndAudio":
			tabNum--;
			superString = superString + "\">"
					+ System.getProperty("line.separator");
			holder = "</audio>";
			tabulate();
			superString = superString + holder;
			break;
		case "#StartVideo":
			holder = "<iframe src=" + '\"';
			superString = superString + holder;
			break;
		case "#EndVideo":
			holder = "\"/>";
			superString = superString + holder;
			break;
		case "#StartNewline":
			holder = "<br>" + System.getProperty("line.separator");
			superString = superString + holder;
			tabulate();
			break;
		default:
			tempText = "";
			grabText();
			superString = superString + tempText.trim();
			break;
		}
	}

	/**
	 * This method prints the correct number of tabs ('\t') the number changes
	 * depending on which tags are current
	 */
	public static void tabulate() {
		for (int i = 0; i < tabNum; i++) {
			superString = superString + '\t';
		}
	}

	/**
	 * This methods collects a string of text tokens into a temporary string
	 * This allows the removal of unwanted whitespace
	 */
	public static void grabText() {
		tempText = holder + ' ';
		if (!stack.isEmpty()) {
			while (!LexicalAnalyzer.isAnnotate(holder)
					&& !LexicalAnalyzer.isAnnotate(stack.peek())) {
				holder = stack.pop();
				tempText = tempText + holder + ' ';
			}
		}
	}

}
